<?php

declare(strict_types=1);

/*
 * This file is part of PHP CS Fixer.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *     Dariusz Rumiński <dariusz.ruminski@gmail.com>
 *
 * This source file is subject to the MIT license that is bundled
 * with this source code in the file LICENSE.
 */

namespace PhpCsFixer\Tests\Fixer\PhpTag;

use PhpCsFixer\Tests\Test\AbstractFixerTestCase;

/**
 * @internal
 *
 * @covers \PhpCsFixer\Fixer\PhpTag\EchoTagSyntaxFixer
 *
 * @extends AbstractFixerTestCase<\PhpCsFixer\Fixer\PhpTag\EchoTagSyntaxFixer>
 *
 * @author Michele Locati <michele@locati.it>
 *
 * @phpstan-import-type _AutogeneratedInputConfiguration from \PhpCsFixer\Fixer\PhpTag\EchoTagSyntaxFixer
 *
 * @no-named-arguments Parameter names are not covered by the backward compatibility promise.
 */
final class EchoTagSyntaxFixerTest extends AbstractFixerTestCase
{
    /**
     * @param _AutogeneratedInputConfiguration $configuration
     *
     * @dataProvider provideFixCases
     */
    public function testFix(string $expected, ?string $input = null, array $configuration = []): void
    {
        $this->fixer->configure($configuration);

        $this->doTest($expected, $input);
    }

    /**
     * @return iterable<int, array{0: string, 1?: null|string, 2?: _AutogeneratedInputConfiguration}>
     */
    public static function provideFixCases(): iterable
    {
        yield [
            '<?= \'Foo\';',
            '<?php echo \'Foo\';',
            ['format' => 'short', 'shorten_simple_statements_only' => true],
        ];

        yield [
            '<?= \'Foo\';',
            '<?php print \'Foo\';',
            ['format' => 'short', 'shorten_simple_statements_only' => true],
        ];

        yield [
            '<?= \'Foo\'; ?> PLAIN TEXT',
            '<?php echo \'Foo\'; ?> PLAIN TEXT',
            ['format' => 'short', 'shorten_simple_statements_only' => true],
        ];

        yield [
            '<?= \'Foo\'; ?> PLAIN TEXT',
            '<?php print \'Foo\'; ?> PLAIN TEXT',
            ['format' => 'short', 'shorten_simple_statements_only' => true],
        ];

        yield [
            'PLAIN TEXT<?= \'Foo\'; ?>',
            'PLAIN TEXT<?php echo \'Foo\'; ?>',
            ['format' => 'short', 'shorten_simple_statements_only' => true],
        ];

        yield [
            'PLAIN TEXT<?= \'Foo\'; ?>',
            'PLAIN TEXT<?php print \'Foo\'; ?>',
            ['format' => 'short', 'shorten_simple_statements_only' => true],
        ];

        yield [
            '<?= \'Foo\'; ?> <?= \'Bar\'; ?>',
            '<?php echo \'Foo\'; ?> <?php echo \'Bar\'; ?>',
            ['format' => 'short', 'shorten_simple_statements_only' => true],
        ];

        yield [
            '<?= \'Foo\'; ?> <?= \'Bar\'; ?>',
            '<?php print \'Foo\'; ?> <?php echo \'Bar\'; ?>',
            ['format' => 'short', 'shorten_simple_statements_only' => true],
        ];

        yield [
            '<?php echo \'Foo\'; someThingElse();',
            null,
            ['format' => 'short', 'shorten_simple_statements_only' => true],
        ];

        yield [
            '<?= \'Foo\'; someThingElse();',
            '<?php echo \'Foo\'; someThingElse();',
            ['format' => 'short', 'shorten_simple_statements_only' => false],
        ];

        yield [
            '<?=/*this */ /** should be in the result*/ \'Foo\';',
            '<?php /*this */ /** should be in the result*/ echo \'Foo\';',
            ['format' => 'short', 'shorten_simple_statements_only' => true],
        ];

        yield [
            <<<'EOT'
                <?=/*comment*/
                  1
                ?>
                EOT,
            <<<'EOT'
                <?php /*comment*/ echo
                  1
                ?>
                EOT,
            ['format' => 'short', 'shorten_simple_statements_only' => true],
        ];

        yield [
            <<<'EOT'
                <?=/*comment*/ 1
                ?>
                EOT,
            <<<'EOT'
                <?php
                  /*comment*/ echo 1
                ?>
                EOT,
            ['format' => 'short', 'shorten_simple_statements_only' => true],
        ];

        yield [
            <<<'EOT'
                <?=/*comment*/
                  1
                ?>
                EOT,
            <<<'EOT'
                <?php
                  /*comment*/
                  echo
                  1
                ?>
                EOT,
            ['format' => 'short', 'shorten_simple_statements_only' => true],
        ];

        $shortToLongFormatCases = [
            ['<?php <fn> 1;', '<?= 1;'],
            ['<?php <fn> 1;', '<?=1;'],
            ['<?php <fn> /**/1;', '<?=/**/1;'],
            ['<?php <fn> /**/ 1;', '<?=/**/ 1;'],
            ['<?php <fn> \'Foo\';', '<?= \'Foo\';'],
            ['<?php <fn> \'Foo\'; ?> PLAIN TEXT', '<?= \'Foo\'; ?> PLAIN TEXT'],
            ['PLAIN TEXT<?php <fn> \'Foo\'; ?>', 'PLAIN TEXT<?= \'Foo\'; ?>'],
            ['<?php <fn> \'Foo\'; ?> <?php <fn> \'Bar\'; ?>', '<?= \'Foo\'; ?> <?= \'Bar\'; ?>'],
            ['<?php <fn> foo();', '<?=foo();'],
        ];

        foreach (['echo', 'print'] as $function) {
            foreach ($shortToLongFormatCases as $case) {
                yield [
                    str_replace('<fn>', $function, $case[0]),
                    str_replace('<fn>', $function, $case[1]),
                    ['format' => 'long', 'long_function' => $function],
                ];
            }
        }
    }
}
